package cn.tworice.backup.executor.impl;

import cn.tworice.backup.executor.BackupExecutor;
import cn.tworice.backup.executor.DatabaseParam;
import com.mongodb.client.FindIterable;
import com.mongodb.client.MongoClient;
import com.mongodb.client.MongoClients;
import com.mongodb.client.MongoCollection;
import com.mongodb.client.MongoDatabase;
import lombok.NoArgsConstructor;
import org.bson.Document;
import org.bson.json.JsonWriterSettings;

import java.io.BufferedWriter;
import java.io.File;
import java.io.FileWriter;
import java.text.SimpleDateFormat;
import java.util.Date;

@NoArgsConstructor
public class MongoBackupExecutor implements BackupExecutor {

    private DatabaseParam dataSourceProperties;
    private MongoClient mongoClient;
    private MongoDatabase mongoDatabase;

    public MongoBackupExecutor(DatabaseParam params) {
        this.dataSourceProperties = params;
    }

    /**
     * 备份整个数据库到指定目录，生成 .js 文件
     * @param path 要备份数据的目录路径
     */
    @Override
    public void backup(StringBuilder path) {
        try {
            connectMongo();
            exportAllCollections(path);
        } finally {
            if (mongoClient != null) {
                mongoClient.close();
            }
        }
    }

    /**
     * 连接 MongoDB
     */
    private void connectMongo() {
        String uri = dataSourceProperties.getUrl();
        mongoClient = MongoClients.create(uri);
        mongoDatabase = mongoClient.getDatabase(dataSourceProperties.getDatabaseName());
    }

    /**
     * 导出所有集合的数据，并生成可执行的 JS 脚本
     * @param path 输出路径构造器
     */
    private void exportAllCollections(StringBuilder path) {
        String dateString = getDateString();
        String dbName = dataSourceProperties.getDatabaseName();
        // 构建脚本文件路径，按数据库分文件
        path.append(File.separator)
                .append(dbName)
                .append("_")
                .append(dateString)
                .append(".js");

        File file = new File(path.toString());
        file.getParentFile().mkdirs();

        try (BufferedWriter writer = new BufferedWriter(new FileWriter(file, false))) {
            // 切换到目标数据库
            writer.write("use " + dbName + ";");
            writer.newLine(); writer.newLine();

            JsonWriterSettings writerSettings = JsonWriterSettings.builder()
                    .indent(false)
                    .build();

            for (String collectionName : mongoDatabase.listCollectionNames()) {
                // 创建集合
                writer.write("db.createCollection(\"" + collectionName + "\");");
                writer.newLine();

                MongoCollection<Document> collection = mongoDatabase.getCollection(collectionName);
                FindIterable<Document> documents = collection.find();

                // 使用 getCollection 形式的插入语句
                for (Document doc : documents) {
                    String json = doc.toJson(writerSettings);
                    writer.write("db.getCollection(\"" + collectionName + "\").insert(" + json + ");");
                    writer.newLine();
                }

                writer.newLine();
            }
        } catch (Exception e) {
            throw new RuntimeException("MongoDB 数据导出异常: " + e.getMessage(), e);
        }
    }

    /**
     * 获取当前时间字符串，例如 202507011430
     */
    private String getDateString() {
        SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMddHHmm");
        return sdf.format(new Date());
    }
}
